В соотвествии с техническим заданием был проведен A/B-тест под кодовым названием recommender_system_test. Тестирование было проведено с 2020-12-07 по 2021-01-04. В тестирование вошли 15% новых пользователей из региона EU, которые были набраны на протяжении двух недель (со старта тестирования по 2020-12-21). Ожидается, что в тест попали 6 тыс. пользователей.
Назначение теста: тестирование изменений, связанных с внедрением улучшенной рекомендательной системы; Ожидаемый эффект: за 14 дней с момента регистрации в системе пользователи покажут улучшение каждой метрики не менее, чем на 10%: конверсии в просмотр карточек товаров — событие product_page просмотры корзины — product_cart покупки — purchase.
Цель исследования:
Ход исследования:
В нашем распоряжении три датасета: ab_project_marketing_events.csv, final_ab_new_users.csv, final_ab_events.csv и . Загрузим имеющиеся данные и посмотрим что содержится в таблицах, информацию о хранимых типах данных, если ли пропуски и явные дубликаты и проведем предобработку при необходимости
<class 'pandas.core.frame.DataFrame'> RangeIndex: 14 entries, 0 to 13 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 14 non-null object 1 regions 14 non-null object 2 start_dt 14 non-null object 3 finish_dt 14 non-null object dtypes: object(4) memory usage: 576.0+ bytes
None
Колонок с пропущенным значением: 0 Количество явных дубликатов: 0
| name | regions | start_dt | finish_dt | |
|---|---|---|---|---|
| 0 | Christmas&New Year Promo | EU, N.America | 2020-12-25 | 2021-01-03 |
| 1 | St. Valentine's Day Giveaway | EU, CIS, APAC, N.America | 2020-02-14 | 2020-02-16 |
| 2 | St. Patric's Day Promo | EU, N.America | 2020-03-17 | 2020-03-19 |
| 3 | Easter Promo | EU, CIS, APAC, N.America | 2020-04-12 | 2020-04-19 |
| 4 | 4th of July Promo | N.America | 2020-07-04 | 2020-07-11 |
| 5 | Black Friday Ads Campaign | EU, CIS, APAC, N.America | 2020-11-26 | 2020-12-01 |
| 6 | Chinese New Year Promo | APAC | 2020-01-25 | 2020-02-07 |
| 7 | Labor day (May 1st) Ads Campaign | EU, CIS, APAC | 2020-05-01 | 2020-05-03 |
| 8 | International Women's Day Promo | EU, CIS, APAC | 2020-03-08 | 2020-03-10 |
| 9 | Victory Day CIS (May 9th) Event | CIS | 2020-05-09 | 2020-05-11 |
| 10 | CIS New Year Gift Lottery | CIS | 2020-12-30 | 2021-01-07 |
| 11 | Dragon Boat Festival Giveaway | APAC | 2020-06-25 | 2020-07-01 |
| 12 | Single's Day Gift Promo | APAC | 2020-11-11 | 2020-11-12 |
| 13 | Chinese Moon Festival | APAC | 2020-10-01 | 2020-10-07 |
Всего датасет содержит 14 записей о маркетинговых мероприятиях. Пропусков и дубликатов нет.
В датасете есть колонки start_dt и finish_dt с типом файла object. Поменяем тип данных на datetime.
Дальнейшая предобработка не требуется, перейдем к следующему датасету
<class 'pandas.core.frame.DataFrame'> RangeIndex: 61733 entries, 0 to 61732 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 user_id 61733 non-null object 1 first_date 61733 non-null object 2 region 61733 non-null object 3 device 61733 non-null object dtypes: object(4) memory usage: 1.9+ MB
None
Колонок с пропущенным значением: 0 Количество явных дубликатов: 0
| user_id | first_date | region | device | |
|---|---|---|---|---|
| 0 | D72A72121175D8BE | 2020-12-07 | EU | PC |
| 1 | F1C668619DFE6E65 | 2020-12-07 | N.America | Android |
| 2 | 2E1BF1D4C37EA01F | 2020-12-07 | EU | PC |
| 3 | 50734A22C0C63768 | 2020-12-07 | EU | iPhone |
| 4 | E1BDDCE0DAFA2679 | 2020-12-07 | N.America | iPhone |
Всего датасет содержит 61733 записи о новых пользователях, дате их прихода, региона и устройства. Пропусков и дубликатов нет.
В датасете есть колонка first_date с типом файла object. Поменяем тип данных на datetime.
Проверим две колонки на неочевидные пропуски и сверим количество уникальных пользователей по user_id
Уникальные регионы ['EU' 'N.America' 'APAC' 'CIS'] Уникальные устройства ['PC' 'Android' 'iPhone' 'Mac'] Количество уникальных пользователей по user_id 61733 Дата самого раннего прихода: 2020-12-07 00:00:00 Дата самого позднего прихода: 2020-12-23 00:00:00
Регионы и устройства не повторяются. Количество уникальных пользователей соответствует числу записей датасета. Дальнейшая предобработка не требуется, перейдем к следующему датасету
<class 'pandas.core.frame.DataFrame'> RangeIndex: 440317 entries, 0 to 440316 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 user_id 440317 non-null object 1 event_dt 440317 non-null object 2 event_name 440317 non-null object 3 details 62740 non-null float64 dtypes: float64(1), object(3) memory usage: 13.4+ MB
None
Колонок с пропущенным значением: 1 Количество явных дубликатов: 0
| user_id | event_dt | event_name | details | |
|---|---|---|---|---|
| 0 | E1BDDCE0DAFA2679 | 2020-12-07 20:22:03 | purchase | 99.99 |
| 1 | 7B6452F081F49504 | 2020-12-07 09:22:53 | purchase | 9.99 |
| 2 | 9CD9F34546DF254C | 2020-12-07 12:59:29 | purchase | 4.99 |
| 3 | 96F27A054B191457 | 2020-12-07 04:02:40 | purchase | 4.99 |
| 4 | 1FD7660FDF94CA1F | 2020-12-07 10:15:09 | purchase | 4.99 |
Всего датасет содержит 440 317 записи о пользовательской активности, времени совершения событий, типе событий и стоимости покупок. Дубликатов нет. Пропуски содержатся в колонке details. Скорей всего они вызваны тем, что стоимость выгружается только для события purchase.
В датасете есть колонки event_dt с типом файла object. Поменяем тип данных на datetime и проверим датасет на события и временной интервал
Количество событий типа purchase: 62740 Уникальные события ['purchase' 'product_cart' 'product_page' 'login'] Дата самого раннего события: 2020-12-07 00:00:33 Дата самого позднего события: 2020-12-30 23:36:33
Количество событий типа purchase совпадает с количеством данных, имеющихся в колонке details. Оставляем пропуски не заполненными
Пропуски проверены, тип данных сменен на корректный. Дальнейшая предобработка не требуется, перейдем к следующему датасету
<class 'pandas.core.frame.DataFrame'> RangeIndex: 18268 entries, 0 to 18267 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 user_id 18268 non-null object 1 group 18268 non-null object 2 ab_test 18268 non-null object dtypes: object(3) memory usage: 428.3+ KB
None
Колонок с пропущенным значением: 0 Количество явных дубликатов: 0
| user_id | group | ab_test | |
|---|---|---|---|
| 0 | D1ABA3E2887B6A73 | A | recommender_system_test |
| 1 | A7A3664BD6242119 | A | recommender_system_test |
| 2 | DABC14FDDFADD29E | A | recommender_system_test |
| 3 | 04988C5DF189632E | A | recommender_system_test |
| 4 | 482F14783456D21B | B | recommender_system_test |
Всего датасет содержит 18 268 записей о пользователях, их распределении по группам и названии теста. Дубликатов нет. Колонок с пропусками тоже нет.
Посмотрим на количество уникальных пользователей по user_id, уникальные названия теста и распределение пользователей по группам
Количество уникальных пользователей по user_id 16666 Участники группы А: 9655 Участники группы В: 8613 Уникальные названия тестирования ['recommender_system_test' 'interface_eu_test']
Датасет содержит данные о двух тестированиях: recommender_system_test и interface_eu_test
Количество уникальных user_id отличается от количества записей. Получается некоторые пользователи попали сразу в две группы или два тестирования. Посмотрим распределение пользователей по типу тестов
Участники тестирования recommender_system_test: 6701 Участники тестирования interface_eu_test: 11567
В тестирование interface_eu_test попало практически в два раза больше пользователей. На этом этапе мы не можем сделать выводы относительно дубликатов поэтому на этапе предобработки не будем их удалять и возьмем исследование в том виде, в каком оно есть
Все данные были проверены и обработаны, если в этом была необходимость.
Были внесены следующие изменения:
ab_project_marketing_events.csv
final_ab_new_users.csv
final_ab_events.csv
Выведем техническое задание и посмотрем какая информация после ознакомления с данными совпадает с ожиданиями, а какая требует уточнения.
Техническое задание
Во время предобработки мы обнаружили, что:
Основную информацию по соответствию удалось получить при ознакомлени с данными. Только два пункта ТЗ остались не проверенными:Аудитория и Ожидаемый эффект.
Изучим эффект от тестирования в следующих этапах анализа, пока посмотрим какую долю на данные момент занимают пользователи тестирования, среди всех новых пользователей
Доля европейских пользователей, попавших в тест: 15.0
В тест вошли 15% от общего числа новых пользователей из Европы, зарегистрированных до 21 декабря . Соответствует ожиданиям ТЗ.
Пункты ТЗ относительно сырых данных проверены. Далее приведем датасет к чистым показателям, оценим дубликаты и скорректируем позиции, которые требуют уточнения.
Разобъем датасет final_ab_participants.csv на два и посмотрим как пересекаются пользователи, чтобы принять решение о том, что делать с дублирующимися пользователями. Помимо этого проверим, есть ли пользователи, попавшие в две группы сразу
Количество пользователей, попавшие в две группы 1602
1602 пользователям присвоены сразу две группы. Посмотрим в каких тестах пользователя присвоена та или иная группа, и есть ли пересечения внутри одного теста
| user_id | group_x | ab_test_x | group_y | ab_test_y | |
|---|---|---|---|---|---|
| 0 | FC3F3E4DA7C85F88 | A | recommender_system_test | B | interface_eu_test |
| 1 | FE2AF0E94DBD470E | A | recommender_system_test | B | interface_eu_test |
| 2 | C5AD06762E628169 | A | recommender_system_test | B | interface_eu_test |
| 3 | 25CE0629AC6B6971 | A | recommender_system_test | B | interface_eu_test |
| 4 | 44EB15AD423DC31C | A | recommender_system_test | B | interface_eu_test |
Пересечение групп внутри recommender_system_test: 0 Пересечение групп внутри interface_eu_test: 0
Внутри групп дублей не найдено. Получается Какие то пользователи попали в контрольную группу одного тестирования и альтернативную группу другого. Такое совпадение может повлиять на поведение пользователей и для частоты эксперемента мы можем взять пользователей группы A из interface_eu_test, которые вошли в группу B целевого теста (recommender_system_test). Прежде чем убирать дубликаты по группам, посмотрим как распределены пользователи по тестам и есть ли среди них другие дубликаты
Пересечение групп A: 482 Пересечение групп B: 344
| user_id | group_x | ab_test_x | group_y | ab_test_y | |
|---|---|---|---|---|---|
| 0 | DABC14FDDFADD29E | A | recommender_system_test | A | interface_eu_test |
| 1 | 04988C5DF189632E | A | recommender_system_test | A | interface_eu_test |
| 2 | B3A2485649E4A012 | A | recommender_system_test | A | interface_eu_test |
| 3 | EAFB9027A27D510C | B | recommender_system_test | A | interface_eu_test |
| 4 | 5D5E6EE92AF6E9E0 | B | recommender_system_test | B | interface_eu_test |
В целях нашего исследования пересечения групп А-А не страшно, они видили изначальный вариант, без изменений. Другое дело пересечение групп В-В. Эти пользователи попали под все тестовые изменения и могут искажать целевые результаты. Для чистоты данных от этих пользователей лучше отказаться.
Посмотрим как выглядит распределение пользователей нашего теста на данный момент
Количество уникальных пользователей по user_id в recommender_system_test 6701 Участники группы А: 3824 Участники группы В: 2877
В сырые данные попали 6 701 пользователей. Распределение по группам не равномерное, 57 на 43, но размер групп достаточно большой, чтобы проверить результаты тестирования. Очистим данные от дубликатов, которые могут исказить исследование
Количество уникальных пользователей по user_id в recommender_system_test 5918 Участники группы А: 3385 Участники группы В: 2533
Выборка сократилась и теперь составляет меньше 6 тыс. участников, но реальное количество не так далеко от ожидаемого. Распределение по группам так и осталось на уровне 57 на 43.
Создадим два новых датасета, которые бедут содержать данные о событиях только тех пользователей, которые корректно вошли в тестирование: один содержащий события, второй - информацию о регистрации. Добавим в таблицу данные о том, к какой группе они отностяться.
| user_id | event_dt | event_name | details | group | ab_test | |
|---|---|---|---|---|---|---|
| 0 | 831887FE7F2D6CBA | 2020-12-07 06:50:29 | purchase | 4.99 | A | recommender_system_test |
| 1 | 831887FE7F2D6CBA | 2020-12-09 02:19:17 | purchase | 99.99 | A | recommender_system_test |
| 2 | 831887FE7F2D6CBA | 2020-12-07 06:50:30 | product_cart | NaN | A | recommender_system_test |
| 3 | 831887FE7F2D6CBA | 2020-12-08 10:52:27 | product_cart | NaN | A | recommender_system_test |
| 4 | 831887FE7F2D6CBA | 2020-12-09 02:19:17 | product_cart | NaN | A | recommender_system_test |
| user_id | first_date | region | device | group | ab_test | |
|---|---|---|---|---|---|---|
| 0 | D72A72121175D8BE | 2020-12-07 | EU | PC | A | recommender_system_test |
| 1 | DD4352CDCF8C3D57 | 2020-12-07 | EU | Android | B | recommender_system_test |
| 2 | 831887FE7F2D6CBA | 2020-12-07 | EU | Android | A | recommender_system_test |
| 3 | 4CB179C7F847320B | 2020-12-07 | EU | iPhone | B | recommender_system_test |
| 4 | 29C92313A98B1176 | 2020-12-07 | APAC | Android | B | recommender_system_test |
Общее количество событий: 21842 Дата самого раннего прихода: 2020-12-07 00:00:00 Дата самого позднего прихода: 2020-12-21 00:00:00
Теперь даты первого появления пользователя соответствуют ТЗ. Однако уже по первым двум записям видно, что не все пользователи, попавшие в усеченный датасет из Евросоюза. Уберем лишние страны и обновим датасеты
Всего пользователей из европы: 46270 Всего пользователей из европы в тестировании: 5568 Доля пользователей, попавших в тест: 13.15
После исключение дубликатов в тест попали лишь 13,15% от новых пользователей.
Ограничим количество дней, которые пользователь провел в тестовой группе до 14 дней в соответствии с ТЗ
| user_id | event_dt | event_name | details | group | ab_test | date | end_of_test | |
|---|---|---|---|---|---|---|---|---|
| 0 | 831887FE7F2D6CBA | 2020-12-07 06:50:29 | purchase | 4.99 | A | recommender_system_test | 2020-12-07 | 2020-12-21 |
| 1 | 831887FE7F2D6CBA | 2020-12-09 02:19:17 | purchase | 99.99 | A | recommender_system_test | 2020-12-09 | 2020-12-21 |
| 2 | 831887FE7F2D6CBA | 2020-12-07 06:50:30 | product_cart | NaN | A | recommender_system_test | 2020-12-07 | 2020-12-21 |
| 3 | 831887FE7F2D6CBA | 2020-12-08 10:52:27 | product_cart | NaN | A | recommender_system_test | 2020-12-08 | 2020-12-21 |
| 4 | 831887FE7F2D6CBA | 2020-12-09 02:19:17 | product_cart | NaN | A | recommender_system_test | 2020-12-09 | 2020-12-21 |
Теперь все пункты ТЗ соблюдены. В очищенном датасете собраны данные о пользователях только recommender_system_test, очищенные от дублей, которые могли повлиять на результаты, и ограниченные 14 днями активности со дня регистрации. Проверим попадает ли исследуемая когорта пользователей под какие либо маркетинговые события
| name | regions | start_dt | finish_dt | |
|---|---|---|---|---|
| 0 | Christmas&New Year Promo | EU, N.America | 2020-12-25 | 2021-01-03 |
Последняя неделя периода наблюдений попадает под промо-мероприятие в честь Рождества и Нового года, которое затрагивает Европейский регион. Это может сказаться на пользовательской активности и исказить результаты, но пока будем иметь эту информацию ввиду и перейдем к исследовательскому этапу
Проведем исследовательский анализ данных и посмотрим распределение событий по выборкам, дням и отдельным этапам.
Для начала выведем распределение событий на пользователя, с учетом принадлежности к группам
Среднее количество событий на пользователя группы А event_name 6.96 dtype: float64 Среднее количество событий на пользователя группы B event_name 5.43 dtype: float64
Так как в группу А попало больше пользователей, общее количество событий распределено неравномерно. Так же, пользователи группы А в среднем совершают больше событий, чем пользователи группы В.
Посмотрим разбивку событий по дням исследования
Посмотрим с какой частотой пользователи входили в тестирование по дням
Больше всего пользователей вошли в тестирование 7, 14 и 21 декабря. В остальном "вход" в тестирование волнообразный
Рассмотрим какие именно события совершают пользователи двух групп в разные дни
Посмотрим распределение доли событий по группам
Посмотрим воронку конверсии по уникальным пользователям с разрезом по группам.
После каждого шага воронки теряется половина пользователей от предыдущего шага. До покупки доходит 1/3 уникальных пользователей. помимо этого, в группе В 0,13% не прошли событие login.
Следующие моменты могут повлиять на точность дальнейшего тестирования
Проведем А/В тестирование и проверим статистическую разницу долей z-критерием.
Проверим статистическую разницу долей конверсии воронки z-критерием.
Всего в воронке участвует четыре события. Так как мы считаем события с момента login, доли пользователей на этом этапе будут равны. Сответственно по остальным событиям воронки формулируем свою нулевую гипотезу:
В связи с этим скорректируем уровень α до 0,0167
1476 429 2279.0 770.0 Результаты теста групп A и B и события product_page p-значение: 7.302688278310043e-06 Отвергаем нулевую гипотезу: между долями есть статистически значимая разница None 686 214 2279.0 770.0 Результаты теста групп A и B и события product_cart p-значение: 0.22463227493216675 Не получилось отвергнуть нулевую гипотезу, нет оснований считать доли разными None 734 219 2279.0 770.0 Результаты теста групп A и B и события purchase p-значение: 0.05131111814183842 Не получилось отвергнуть нулевую гипотезу, нет оснований считать доли разными None
Две из трех нулевых гипотез не удалось отвегрнуть.
Между долями групп A и B и события product_page есть статистически значимая разница.
Посмотрим удалось ли добиться ожидаемого эффекта от нововведений, а именно: за 14 дней с момента регистрации в системе пользователи покажут улучшение каждой метрики не менее, чем на 10%:
Постоим график с кумулятивными показателями, так как пользователи пришли в разные даты, и сравнум их среди двух групп
Все три графика показывают одинаковую картину:
Выводы о А/В-тестировании
С учетом временного периода и значительно меньшем количестве участников теста, после удаления пользователей попавших в две группы и из других регионов, не рекомендую опираться на результаты данного теста
Для целей исследования были предоставленны четыре датасета: ab_project_marketing_events.csv - календарь маркетинговых событий на 2020 год, final_ab_new_users.csv - все пользователи, зарегистрировавшиеся в интернет-магазине в период с 7 по 21 декабря 2020 года, final_ab_events.csv - все события новых пользователей в период с 7 декабря 2020 по 4 января 2021 года и final_ab_participants.csv - таблица участников тестов
В ходе предобработки были внесены следующие изменения:
ab_project_marketing_events.csv
final_ab_new_users.csv
final_ab_events.csv
Сырые данные были проверенны на корректность, часть соответствовали ТЗ, другая часть требовала уточнения. После уточнения выяснилось, что:
При исследовании данных были выделены следующие моменты:
На основании исследования воронка была определена следующим образом:
login --> product_page --> product_cart --> purchase
После первых трех шагов воронки теряется половина пользователей от предыдущего шага. Покупка совершается чаще, чем посещение корзины. До покупки доходит 1/3 уникальных пользователей.
Так как в воронке участвует четыре события, по каждому событию была сформулирвоана своя нулевая гипотеза:
В связи с этим уровень α был скорректирован до 0,0125
2 и 3 нулевые гипотезы не удалось отвегрнуть. 1 нулевая гипотеза была отвергнута.
Между долями групп A и B и события product_page есть статистически значимая разница
Следующие факторы вызвали сомнение, что тестирование было проведено корректно:
В связи с этим не рекомендую принимать решения на основе этих данных
Благодарю за внимание!